<script>
import { defineComponent, ref, computed, watch } from 'vue'
import { createNamespace, transformSize, transformStyleSize, getInputValue } from '../utils'
import { getInputType } from './helper'
import FanIcon from '../icon/icon.vue'

export default defineComponent({
  name: createNamespace('InputNumber')[0],
  options: {
    // https://uniapp.dcloud.io/matter.html#mp
    virtualHost: true
  },
  components: { FanIcon },
  props: {
    modelValue: {
      type: [Number, String]
    },
    // 是否只允许输入整数
    integer: {
      type: Boolean,
      default: true
    },
    // 计数器步长
    step: {
      type: Number,
      default: 1
    },
    // 按钮大小
    actionSize: {
      type: [Number, String],
      default: 22
    },
    // 按钮颜色
    actionColor: {
      type: String
    },
    inputWidth: {
      type: [Number, String],
      default: 32
    },
    inputStyle: String,
    min: {
      type: Number,
      default: 1
    },
    max: {
      type: Number,
      default: 99999
    },
    // 减少按钮图标名或网络地址，有值则覆盖默认按钮
    minusIcon: {
      type: String
    },
    // 增加按钮图标名或网络地址
    plusIcon: {
      type: String
    }
  },
  emits: ['update:modelValue', 'input', 'change', 'overlimit'],
  setup(props, context) {

    const innerValue = ref(1)
    const inputType = computed(() => getInputType(props.integer))
    const actionStyle = computed(() => {
      const size = transformSize(props.actionSize)
      return `width:${size};height:${size};`
    })
    const theInputStyle = computed(() => {
      const size = transformSize(props.actionSize)
      const width = transformSize(props.inputWidth)
      return `width:${width};height:${size};line-height:${size};${transformStyleSize(props.inputStyle)}`
    })

    const minusDisabled = computed(() => innerValue.value <= props.min)
    const plusDisabled = computed(() => props.max && innerValue.value >= props.max)

    watch(
      () => props.modelValue,
      (val) => {
        if ((val || val === 0) && val !== innerValue.value) innerValue.value = val
      },
      { immediate: true }
    )
    watch(innerValue, (val) => {
      if (val !== props.modelValue) context.emit('update:modelValue', val)
      context.emit('input', val)
      context.emit('change', val)
    })

    const onInput = (e) => {
      let value = Number(getInputValue(e)) || ''
      const { min, max } = props
      if (!value || value < min) {
        value = min
        context.emit('overlimit', 'minus')
      } else if ((max || max === 0) && value > max) {
        value = max
        context.emit('overlimit', 'plus')
      }
      innerValue.value = value
    }

    const minus = () => {
      const { step, min } = props
      const val = innerValue.value - step
      if (val < min) {
        if (step > 1) innerValue.value = min
        else context.emit('overlimit', 'minus')
      } else {
        innerValue.value = val
      }
    }
    const plus = () => {
      const { step, max } = props
      const val = innerValue.value + step
      if ((max || max === 0) && val > max) {
        if (step > 1) innerValue.value = max
        else context.emit('overlimit', 'plus')
      } else {
        innerValue.value = val
      }
    }

    return {
      innerValue,
      inputType,
      actionStyle,
      theInputStyle,
      minusDisabled,
      plusDisabled,
      onInput,
      minus,
      plus
    }
  }
})
</script>

<template>
  <div class="fan-input-num">
    <button class="fan-flex fan-align-center fan-justify-center fan-input-num__action"
      :class="{ 'fan-input-num--disabled': minusDisabled }" :style="actionStyle" @click="minus">
      <div v-if="!minusIcon" class="fan-input-num__hl" :style="{ backgroundColor: actionColor }"></div>
      <FanIcon v-else :name="minusIcon" :size="actionSize * 0.7" :color="actionColor" />
    </button>

    <input class="fan-input-num__field" :style="theInputStyle" controlled v-model="innerValue" :type="inputType.type"
      :inputmode="inputType.mode" @input="onInput" />

    <button class="fan-flex fan-align-center fan-justify-center fan-input-num__action"
      :class="{ 'fan-input-num--disabled': plusDisabled }" :style="actionStyle" @click="plus">
      <template v-if="!plusIcon">
        <div class="fan-input-num__hl" :style="{ backgroundColor: actionColor }"></div>
        <div class="fan-input-num__vl" :style="{ backgroundColor: actionColor }"></div>
      </template>
      <FanIcon v-else :name="plusIcon" :size="actionSize * 0.7" :color="actionColor" />
    </button>
  </div>
</template>

<style lang="less">
.fan-input-num {
  display: inline-flex;
  justify-content: center;
  align-items: center;

  &__action {
    background: transparent;
    outline: none;
    padding: 0;
    margin: 0;
    line-height: 1;
    border: 0;
    border-radius: 4px 0 0 4px;
    position: relative;
    width: 28px;
    height: 28px;

    &:active {
      opacity: 0.7;
    }

    &::after {
      border: 0;
    }
  }

  &--disabled {
    opacity: 0.5;
  }

  &__hl,
  &__vl {
    position: absolute;
    top: 50%;
    left: 50%;
    background-color: #626263;
    transform: translate(-50%, -50%);
  }

  &__hl {
    width: 50%;
    height: 2px;
  }

  &__vl {
    width: 2px;
    height: 50%;
  }

  &__field {
    font-size: 14px;
    color: #323233;
    line-height: 1;
    text-align: center;
    padding: 0;
    margin: 0 2px;
    background: transparent;
    border: 0;
  }
}
</style>